#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <errno.h>
#include <sys/time.h>
#include <pthread.h>
#include <signal.h>
#include <semaphore.h>
#include <sched.h>
#include "quant.h"
#include <dirent.h>
#include <execinfo.h>
#include <string.h>
#include <syslog.h>
#include <sched.h>
#ifdef IPP
#include <ipp.h>
#include <ippdefs.h>
#endif

#define DEBUG
char filename[598][15];
char *read_file,*write_file;
int Framepointer=0;




/*............................................................ POSIX thread declarations and scheduling attribute.................................*/
pthread_t threadread;
pthread_t threadwrite;
pthread_t proc1,proc2;
pthread_t main_thread;
pthread_attr_t rt_sched_attr;
pthread_attr_t main_sched_attr;
int rt_max_prio, rt_min_prio, min, old_ceiling, new_ceiling;
struct sched_param rt_param;
struct sched_param nrt_param;
struct sched_param main_param;

typedef struct _threadParamsType
{
	int threadID;
	unsigned int microsecs;
	double digestsPerSec;
} threadParamsType;
#define FALSE 0
#define SCHED_POLICY SCHED_FIFO
pthread_t threads[4];
pthread_t tstThreadHandle[4];
threadParamsType threadParams[4];
pthread_attr_t rt_sched_attr;
pthread_attr_t tstThread_sched_attr;
int rt_max_prio, rt_min_prio, min, old_ceiling, new_ceiling;
struct sched_param rt_param;
struct sched_param nrt_param;
struct sched_param tstThread_param;
int threadActiveCnt=0, threadActive=FALSE;
sem_t startIOWorker[1],startProcessWorker, queuebuild;


void getfilename()
{
int y=48,i,x=48,w=48,z=49;

for(i=0;i<598;i++)
{
filename[i][0] = 'F';
filename[i][1] ='r';
filename[i][2] ='a';
filename[i][3] ='m';
filename[i][4] ='e';
filename[i][5] ='-';
filename[i][6] =w;
filename[i][7] =x;
filename[i][8] =y;
filename[i][9] =z;
filename[i][10] ='.';
filename[i][11] ='p';
filename[i][12] ='p';
filename[i][13] ='m';
filename[i][14] ='\0';
z++;
if ((x==58)&&(y==58)&&(z==58))
{w++;
x=48;y=48;z=48;}
if ((y==57)&&(z==58))
{x++;
y=48;z=48;}
if (z==58)
{y++;
z=48;}
}
}



/*....................................................................The Write to File function.....................................................*/
void IOwrite(int FrameCount)

{

int fdout,i,j,dimx=320,dimy=240,r1,r2,r3;


	write_file[0]='\0';
	strcat(write_file,Outputdir);
	strcat(write_file,filename[FrameCount]);
	printf("Writing Frame:%s\n",write_file);
 	FILE *fp = fopen(write_file, "wb");
 	
    //printf("output file opened");
	(void) fprintf(fp, "P6\n%d %d\n255\n", dimx, dimy);

    	for(i=0; i<76800; i++)
    	{
    		UINT8 color[3];
		color[0]=quant[FrameCount].convR[i];
		color[1]=quant[FrameCount].convG[i];
		color[2]=quant[FrameCount].convB[i];
	
		(void)fwrite(color,3,1,fp);
	}
   (void)fclose(fp);
    
}



/*.................................................................The Read from File function.....................................................*/

void IOread ()
{
int FrameCount=0;
int bytesRead=0,bytesLeft,i,j;
int fdin,rc2;

printf("Start read %d\n",FrameCount);
do
{
	
	sem_wait(&startIOWorker[0]);
	read_file[0]='\0';
	strcat(read_file,Inputdir);
	strcat(read_file,filename[FrameCount]);
	//printf("filename:%s\n",filename[FrameCount]);
	//printf("\nRead File:%s\n",read_file);
	if((fdin = open(read_file, O_RDONLY, 0644))<0)
	{printf("error opening file\n");}
	bytesLeft=21;

  
    	do
    	{
     	   //printf("bytesRead=%d, bytesLeft=%d\n", bytesRead, bytesLeft);
      	  bytesRead=read(fdin, (void *)quant[FrameCount].header, bytesLeft);
       	 bytesLeft -= bytesRead;
   	 } while(bytesLeft > 0);
	
   	 quant[FrameCount].header[21]='\0';
	//printf("header read\n");
   	// printf("header = %s\n", quant[FrameCount].header);
   	 // printf("header = %s\n", header[1]);

   	 // Read RGB data
   	     		for(i=0; i<76800; i++)
    			{
			//printf("reading RGB of %d\n",i);
       			 	if((read(fdin, (void *)&quant[FrameCount].R[i], 1))==-1) printf("error read R of pixel %d",i); quant[FrameCount].convR[i]=quant[FrameCount].R[i];
        			if((read(fdin, (void *)&quant[FrameCount].G[i], 1))==-1) printf("error read G of pixel %d",i); quant[FrameCount].convG[i]=quant[FrameCount].G[i];
        			if((read(fdin, (void *)&quant[FrameCount].B[i], 1))==-1) printf("error read B of pixel %d",i); quant[FrameCount].convB[i]=quant[FrameCount].B[i];
				//printf("REad RGB of %d\n",i);
				//printf("quant[%d].R[%d]=%d\n",FrameCount,i,quant[FrameCount].R[i]);
	
    			}	
    	

     close(fdin); 
     printf("\nDone Read:%d\n",FrameCount);
     sem_post(&startProcessWorker); 
     sem_post(&queuebuild); 
     FrameCount++;
} while (FrameCount<FRAMECOUNT);

}


/*.....................................................................The Frame process function.............................................................................*/
void FrameProcess (int Frameprocpoint)
{
printf("processing started for Frame: %d\n",Frameprocpoint);
int rc1;
colorquant(quant[Frameprocpoint]);
#ifdef DEBUG
sharprof(quant[Frameprocpoint]);
#endif
rc1 = pthread_create(&threads[1],NULL,IOwrite,Frameprocpoint);

}




/*....................................................................................Thread variable initialization.....................................................................*/



void SetPolicy()
{
	int rc;
   pthread_attr_init(&rt_sched_attr);
   pthread_attr_init(&main_sched_attr);
   pthread_attr_setinheritsched(&rt_sched_attr, PTHREAD_EXPLICIT_SCHED);
   pthread_attr_setschedpolicy(&rt_sched_attr, SCHED_FIFO);
   pthread_attr_setinheritsched(&main_sched_attr, PTHREAD_EXPLICIT_SCHED);
   pthread_attr_setschedpolicy(&main_sched_attr, SCHED_FIFO);

   rt_max_prio = sched_get_priority_max(SCHED_FIFO);
   rt_min_prio = sched_get_priority_min(SCHED_FIFO);

   rc=sched_getparam(getpid(), &nrt_param);
   rt_param.sched_priority = rt_max_prio;
   rc=sched_setscheduler(getpid(), SCHED_FIFO, &rt_param);

   if (rc)
   {
       printf("ERROR; sched_setscheduler rc is %d\n", rc); perror(NULL); exit(-1);
   }

   printf("After adjustments to scheduling policy:\n");
  

   printf("min prio = %d, max prio = %d\n", rt_min_prio, rt_max_prio);
  


   rt_param.sched_priority = rt_max_prio-1;
   pthread_attr_setschedparam(&rt_sched_attr, &rt_param);

   main_param.sched_priority = rt_max_prio;
   pthread_attr_setschedparam(&main_sched_attr, &main_param);

}




/*.......................................................................Main...............................................................................................*/

int main()
{
	char *error;
    	int i, j,fdout,fdin,rc,rc1,rc2;
	
	read_file = (char*)malloc(29);
	write_file = (char*)malloc(30);
	SetPolicy();
	getfilename();
   	sem_init (&startIOWorker[0],0,30);
	sem_init(&startProcessWorker,0,-30);
	sem_init(&queuebuild,0,-30);
	rc2 = pthread_create(&threadread,NULL,IOread,NULL);
	//printf("\n30 frames in\n");
	//pthread_join(threadread,0);
	sem_wait(&queuebuild);
	do
	{
	sem_wait(&startProcessWorker);
	
	#ifdef DEBUG
	rc = pthread_create(&proc1,&rt_sched_attr, FrameProcess, Framepointer);
	Framepointer++;//fprintf(stderr, "thread create rc =%d",rc);
	rc1 = pthread_create(&proc2,&rt_sched_attr,FrameProcess, Framepointer); 
	Framepointer++;
	#endif
	sem_post(&startIOWorker[0]);
	sem_post(&startIOWorker[0]);
	} while (Framepointer<(FRAMECOUNT/2));
	pthread_join(threadread,0);
	pthread_join(proc1,0);
	pthread_join(proc2,0);
	
	free(read_file);
}

